﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utiles.Persistencia;
using System.Data.SqlClient;
using EntidadesDeNegocio;
using Utiles.Excepcion;

namespace PersistenciaSql
{
    public class BrokerDiseno:Broker
    {
        public override void Insertar(ObjetoPersistente obj)
        {
            int oid = ObtenerUltimoOid() + 1;            
            Diseno dis = (Diseno)obj;
            dis.Oid = oid;
            List<Componente> lstComponentes = dis.ListaComponentes;
            SqlConnection conn = ConexionBDManejador.CreaConexion();                      
            string sql =
                @"Insert into Diseno (Oid,Nombre,Descripcion,Costo,CostoAgregado,FechaService,Medio)" +
                "values (@Oid,@Nombre,@Descripcion,@Costo,@CostoAgregado,@FechaService,@Medio)";
            
            SqlCommand comm = new SqlCommand(sql, conn);
            comm.Parameters.Add("@Oid", System.Data.SqlDbType.Int).Value = oid;
            comm.Parameters.Add("@Nombre", System.Data.SqlDbType.Text).Value = dis.Nombre;
            comm.Parameters.Add("@Descripcion", System.Data.SqlDbType.Text).Value = dis.Medio.ToString();
            comm.Parameters.Add("@Costo", System.Data.SqlDbType.Decimal).Value = dis.Costo;
            comm.Parameters.Add("@CostoAgregado", System.Data.SqlDbType.Decimal).Value = dis.CostoAgregado;
            comm.Parameters.Add("@FechaService", System.Data.SqlDbType.DateTime).Value = dis.FechaService;
            comm.Parameters.Add("@Medio", System.Data.SqlDbType.Text).Value = dis.Medio.ToString();
            try
            {
                conn.Open();
                comm.ExecuteNonQuery();
                CargarComponentes(dis,conn);
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al insertar diseno: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }
            
        }

        private void CargarComponentes(Diseno dis, SqlConnection conn)
        {
            
            try
            {                
                foreach (Componente c in dis.ListaComponentes)
                {
                    string sql = "Insert into DisenoComponente (IdDiseno,IdComponente,CantidadComp)" +
                                    "values (@IdDiseno,@IdComponente,@CantidadComp)";
                    SqlCommand comm = new SqlCommand(sql, conn);
                    comm.Parameters.Add("@IdDiseno", System.Data.SqlDbType.Int).Value = dis.Oid;
                    comm.Parameters.Add("@IdComponente", System.Data.SqlDbType.Int).Value = c.Oid;
                    comm.Parameters.Add("@CantidadComp", System.Data.SqlDbType.Int).Value = c.Cantidad;
                    comm.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al guardar composicion del Diseno: " + ex.Message);
            }
            // No se realiza el close del connection porque lo realiza el finally del metodo Insertar            
        }

        public override void Actualizar(ObjetoPersistente obj)
        {
            string sql = @"Update Diseno set " +
                           "  Nombre=@Nombre " +                          
                           ", Descripcion = @Descripcion" +
                           ", Costo = @Costo" +
                           ", CostoAgregado = @CostoAgregado" +
                           ", FechaService = @FechaService" +
                           ", Medio = @Medio" +
                           " Where Oid = @Oid ";            

            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);
            Diseno dis = (Diseno)obj;
            comm.Parameters.Add("@Oid", System.Data.SqlDbType.Int).Value = dis.Oid;
            comm.Parameters.Add("@Nombre", System.Data.SqlDbType.Text).Value = dis.Nombre;
            comm.Parameters.Add("@Descripcion", System.Data.SqlDbType.Text).Value = dis.Descripcion;
            comm.Parameters.Add("@Costo", System.Data.SqlDbType.Decimal).Value = dis.Costo;
            comm.Parameters.Add("@CostoAgregado", System.Data.SqlDbType.Decimal).Value = dis.CostoAgregado;            
            comm.Parameters.Add("@FechaService", System.Data.SqlDbType.DateTime).Value = dis.FechaService;                    
            comm.Parameters.Add("@Medio", System.Data.SqlDbType.Text).Value = dis.Medio.ToString();

            try
            {
                conn.Open();
                comm.ExecuteNonQuery();
                BorrarComponentesDelDiseno(dis, conn);
                CargarComponentes(dis, conn);
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al actualizar diseño: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }  
        }

        public override void Borrar(ObjetoPersistente obj)
        {
            string sql = "Delete from diseno Where Oid= @Oid";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);
            Diseno dis = (Diseno)obj;
            comm.Parameters.Add("@Oid", System.Data.SqlDbType.Int).Value = dis.Oid;            
            try
            {
                conn.Open();
                BorrarComponentesDelDiseno(dis, conn);
                comm.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al borrar Diseño: " + ex.Message);
            }
            finally
            {
                conn.Close();
            } 
        }

        private void BorrarComponentesDelDiseno(Diseno dis, SqlConnection conn)
        {
            try
            {
                foreach (Componente c in dis.ListaComponentes)
                {
                    string sql = "Delete from DisenoComponente " +
                                "where idDiseno = @idDiseno";
                    SqlCommand comm = new SqlCommand(sql, conn);
                    comm.Parameters.Add("@IdDiseno", System.Data.SqlDbType.Int).Value = dis.Oid;
                    comm.Parameters.Add("@IdComponente", System.Data.SqlDbType.Int).Value = c.Oid;                    
                    comm.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al borrar composicion del Diseno: " + ex.Message);
            }
            // No se realiza el close del connection porque lo realiza el finally del metodo Actualizar       
        }


        public override List<ObjetoPersistente> SeleccionaTodo()
        {
            List<ObjetoPersistente> listaRetorno = new List<ObjetoPersistente>();
            
            string sql = "Select * From Diseno";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);
            try
            {
                conn.Open();
                SqlDataReader reader = comm.ExecuteReader();
                while (reader.Read())
                {
                    Diseno dis = new Diseno();
                    dis.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                    dis.Nombre = reader.GetString(reader.GetOrdinal("Nombre"));
                    dis.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                    dis.CostoAgregado = reader.GetDecimal(reader.GetOrdinal("CostoAgregado"));
                    dis.Descripcion = reader.GetString(reader.GetOrdinal("Medio"));
                    dis.ListaComponentes = ListaComposicion(dis.Oid);
                    listaRetorno.Add(dis);
                }
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al seleccionar los componentes: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }
            return listaRetorno;
        }

        public override ObjetoPersistente SeleccionaUno(ObjetoPersistente obj)
        {
            throw new NotImplementedException();   
        }

        public override int ObtenerUltimoOid()
        {
            string sql = "Select Max(Oid) From Diseno";
            SqlConnection con = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, con);
            try
            {
                con.Open();
                object o = comm.ExecuteScalar();
                if (o.ToString() == string.Empty)
                    return 0;
                else
                    return (int)o;
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error para obtener el ultimo id de la tabla componente: " + ex.Message);
            }
            finally
            {
                con.Close();
            }           
        }


        private List<Componente> ListaComposicion(int oidDiseno)
        {
            List<Componente> listaResultado = new List<Componente>();
            string sqladitional = "Select c.*, d.CantidadComp From Componentes c , DisenoComponente d "+
                "where c.Oid = d.IdComponente and  d.IdDiseno=@IdDiseno";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand commAditional = new SqlCommand(sqladitional, conn);
            commAditional.Parameters.Add("@IdDiseno", System.Data.SqlDbType.Int).Value = oidDiseno;
            try
            {
                conn.Open();
                SqlDataReader reader = commAditional.ExecuteReader();
                while (reader.Read())
                {
                    string tipo = reader.GetString(reader.GetOrdinal("TipoComponente"));
                    if (tipo == TipoComponente.PiezaAcuatica.ToString())
                    {
                        PiezaAcuatica comp = new PiezaAcuatica();
                        comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                        comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                        comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                        comp.Medio = MedioComponente.Acuatico;
                        comp.Cantidad = reader.GetInt32(reader.GetOrdinal("CantidadComp"));
                        comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                        comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                        comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                        comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                        comp.Profundidad = reader.GetDecimal(reader.GetOrdinal("Profundidad"));
                        listaResultado.Add(comp);
                    }
                    if (tipo == TipoComponente.PiezaAerea.ToString())
                    {
                        PiezaAerea comp = new PiezaAerea();
                        comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                        comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                        comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                        comp.Medio = MedioComponente.Acuatico;
                        comp.Cantidad = reader.GetInt32(reader.GetOrdinal("CantidadComp"));
                        comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                        comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                        comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                        comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                        comp.Altitud = reader.GetDecimal(reader.GetOrdinal("Altitud"));
                        comp.Velocidad = reader.GetDecimal(reader.GetOrdinal("Velocidad"));
                        listaResultado.Add(comp);
                    }
                    if (tipo == TipoComponente.PiezaTerrestre.ToString())
                    {
                        PiezaTerrestre comp = new PiezaTerrestre();
                        comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                        comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                        comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                        comp.Medio = MedioComponente.Acuatico;
                        comp.Cantidad = reader.GetInt32(reader.GetOrdinal("CantidadComp"));
                        comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                        comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                        comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                        comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                        comp.Temperatura = reader.GetDecimal(reader.GetOrdinal("Temperatura"));
                        listaResultado.Add(comp);
                    }
                    if (tipo == TipoComponente.Robot.ToString())
                    {
                        Robot comp = new Robot();
                        comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                        comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                        comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                        comp.Medio = MedioComponente.Acuatico;
                        comp.Cantidad = reader.GetInt32(reader.GetOrdinal("CantidadComp"));
                        comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                        comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                        comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                        comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                        comp.ListaComposicion = new List<Componente>();
                        comp.ListaComposicion = ListaComposicion(comp.Oid,conn);
                        listaResultado.Add(comp);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al seleccionar los componentes de un Diseño: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }
            return listaResultado;
        }

        private List<Componente> ListaComposicion(int oidPadre, SqlConnection con)
        {
            List<Componente> listaResultado = new List<Componente>();
            string sqladitional = "Select c.*,cc.CantidadComp From Componentes c INNER JOIN ComponenteComp cc ON c.Oid=cc.IdComponenteHijo Where cc.IdComponentePadre=@IdComponentePadre ";
            SqlCommand comm1 = con.CreateCommand();
            comm1.CommandText = sqladitional;
            comm1.CommandType = System.Data.CommandType.Text;

            try
            {

                comm1.Parameters.Add("@IdComponentePadre", System.Data.SqlDbType.Int).Value = oidPadre;
                using (SqlDataReader reader1 = comm1.ExecuteReader())
                {
                    while (reader1.Read())
                    {
                        string tipo = reader1.GetString(reader1.GetOrdinal("TipoComponente"));
                        if (tipo == TipoComponente.PiezaAcuatica.ToString())
                        {
                            PiezaAcuatica comp = new PiezaAcuatica();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Profundidad = reader1.GetDecimal(reader1.GetOrdinal("Profundidad"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaAerea.ToString())
                        {
                            PiezaAerea comp = new PiezaAerea();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Altitud = reader1.GetDecimal(reader1.GetOrdinal("Altitud"));
                            comp.Velocidad = reader1.GetDecimal(reader1.GetOrdinal("Velocidad"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaTerrestre.ToString())
                        {
                            PiezaTerrestre comp = new PiezaTerrestre();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Temperatura = reader1.GetDecimal(reader1.GetOrdinal("Temperatura"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.Robot.ToString())
                        {
                            Robot comp = new Robot();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.ListaComposicion = new List<Componente>();
                            comp.ListaComposicion = ListaComposicion(comp.Oid, con);
                            listaResultado.Add(comp);
                        }
                    }
                }

                return listaResultado;
            }
            catch (Exception ex)
            {

                throw new BDExcepcion("Error al seleccionar los componentes: " + ex.Message);
            }
        }


    }




}
